/**
 * @author Dan
 */
 //HTML class definitions
// Xable: Item has already been made into an explodable item
// Xi: an explodable item. And item that will be effected by an explosion
// Xh: an element that has been hidden because it has already been exploded and another Aboslute object has been created in its place
// Xt: an exploded element that will have its tick function executed

 /******************* timer ****************/
var Timer = {

    TimerId: 0,
    Interval: 100,

    Start: function () {
        if (this._TimerId == null) {
            this._Interval = 100;
            TimerId = setInterval(Timer.Tick, 100);
        }
    },

    Stop: function () {
        if (this.TimerId != null) {
            clearInterval(this.TimerId);
        }
    },

    Tick: function () {
        jQuery('.Xt').Tick();
    }

}

var TimerStack = {

    Stack: new Array(),
    LastProcessedIdx: 0,

    Add: function (functionCall, Id) {
    },

    ProcessNext: function () {
    }

}
/******************* timer END ****************/

function ConvertPage_BlowUpable() {

    //find all p tags

    //go through each p tag, which has not already been made Xable
    $('p:not(.Xable)').prepareWords();

}

function BlowUp(X, Y, Radius, CenterStrength, DiminishingFactor) {

    if (typeof Radius === 'undefined') { Radius = 50; }
    if (typeof CenterStrength === 'undefined') { CenterStrength = 50; }
    if (typeof DiminishingFactor === 'undefined') { DiminishingFactor = 1; }

    //jQuery('.t').Spin(3);
    //jQuery('.t').attr('style', '-moz-transform: rotate(-7.5deg); -o-transform: rotate(-7.5deg); -webkit-transform: rotate(-7.5deg); ' +
    //     ' -webkit-transform-origin: 0 0 ; filter:  progid:DXImageTransform.Microsoft.BasicImage(rotation=3.917);' +
    //     ' -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3.917)";');
    
    //loop through all points in square containing circle, 
    // and test each point is in the circle
    var SquareX = X - Radius, 
        SquareY = Y - Radius, 
        SquareX2 = X + Radius, 
        SquareY2 = Y + Radius,
        RadiusSquared = Radius ^ 2,
        ElementsList = {};

    DG('SquareX:' + SquareX + ', SquareX2:' + SquareX2 + ', SquareY:' + SquareY + ' SquareY2:' + SquareY2);

    for (var PointY = SquareY; PointY < SquareY2; PointY++) {
        for (var PointX = SquareX; PointX < SquareX2; PointX++) {

            var DistanceFromCenter = Math.sqrt(Math.abs(PointX - X) ^ 2 + Math.abs(PointY - Y) ^ 2);
            var VectorX = PointX - X, VectorY = PointY - Y;

            if (DistanceFromCenter < Radius) {

                var Element = $(document.elementFromPoint(PointX, PointY));

                if (Element.hasClass('Xi')) {

                    var Position = Element.position();
                    var ElId = Position.top + ',' + Position.left;

                    if (!ElementsList[ElId]) {
                        ElementsList[ElId] = Element;
                        Element.affectedByExplosion(VectorX, VectorY, DistanceFromCenter, CenterStrength, DiminishingFactor, Radius);
                    }

                }
            }

        }
    }
    
}

$.fn.extend({
    VelocityX: 0,
    VelocityY: 0,
    SpinRnd: function (MinSpinRate, MaxSpinRate) {
        if (RandomFromTo(0, 1)) {
            this.Spin(RandomFromTo(MinSpinRate, MaxSpinRate));
        } else {
            this.Spin(-RandomFromTo(MinSpinRate, MaxSpinRate));
        }
    },
    Spin: function (SpinRate) {
        for (var i = 0; i < this.length; i++) {
            obj = this[i];
            obj.SpinPosition = 0;
            obj.SpinRate = SpinRate;
        }
    },
    ApplyForce: function (ForceVectorX, ForceVectorY, ForceTickCount) {
        for (var i = 0; i < this.length; i++) {
            obj = this[i];
            if (!obj.AppliedForces) {
                obj.AppliedForceIdx = 0;
                obj.AppliedForces = new Array();
            }
            obj.AppliedForces[obj.AppliedForceIdx] = { ForceVectorX: ForceVectorX, ForceVectorY: ForceVectorY, ForceTickCount: ForceTickCount };
        }
    },
    Tick: function () {
        for (var i = 0; i < this.length; i++) {
            obj = this[i];
            jQobj = $(obj);
            if (typeof obj.SpinRate !== 'undefined' && obj.SpinRate != null) {
                obj.SpinPosition += obj.SpinRate;
                obj.SpinPosition = (obj.SpinPosition % 360);
                jQobj.rotate(obj.SpinPosition);
            }

            if (!typeof obj.AppliedForces !== 'undefined' && obj.AppliedForces != null) {
                var idx = 0;
                while (idx < obj.AppliedForces.length) {
                    var AppliedForces = obj.AppliedForces[idx];
                    if (!obj.VelocityX) { obj.VelocityX = 0; }
                    if (!obj.VelocityY) { obj.VelocityY = 0; }
                    obj.VelocityX = obj.VelocityX + AppliedForces.ForceVectorX;
                    obj.VelocityY = obj.VelocityY + AppliedForces.ForceVectorY;
                    obj.ForceTickCount = obj.ForceTickCount - 1;
                    if (obj.ForceTickCount == 0) {
                        obj.AppliedForces.splice(idx, 1);
                    } else {
                        idx++;
                    }
                }
            }

            if (obj.VelocityX != 0 && obj.VelocityY != 0) {
                var Position = jQobj.position();
                jQobj.css('top', (Position.top + Math.floor(obj.VelocityX)) + 'px').css('left', (Position.left + Math.floor(obj.VelocityY)) + 'px');
            }

            if (!jQobj.isInView()) {
                jQobj.remove();
            }
        }
    },
    isInView: function () {
        var rect = this[0].getBoundingClientRect();
        return (rect.top >= 0 &&
                rect.left >= 0 &&
                rect.bottom <= window.innerHeight &&
                rect.right <= window.innerWidth);
    },
    prepareWords: function () {
        //this.wrapInner("<span class='a' />");
        this.contents().each(prepareWords_Do);

        function prepareWords_Do() {
            var nn = this.nodeName.toLowerCase();
            if (nn === '#text') {

                convertTextNode(this);

            } else if (this.nodeType === 1 && this.childNodes && this.childNodes[0] && nn !== 'script' && nn !== 'textarea') {
                $(this).contents().each(prepareWords_Do);
            }
        }
        return this;
    },
    affectedByExplosion: function (ExVectorX, ExVectorY, DistanceFromCenter, CenterStrength, DiminishingFactor, ExplosionRadius) {

        this.removeClass('Xi');

        //Create the new element
        var NewElement = this.clone();
        var Position = this.position();

        NewElement.addClass('Xt').css('top', Position.top + 'px').css('left', Position.left + 'px').css('position', 'absolute');

        var Strength = (CenterStrength / ExplosionRadius) * DistanceFromCenter;

        //Set the spin
        var MaxSpinRate = (Strength) + 10;
        var MinSpinRate = (Strength) - 10;
        NewElement.SpinRnd(MinSpinRate, MaxSpinRate);

        //Apply a force
        if (Math.floor(ExVectorX / 10) == 0) { ExVectorX = 1; }
        if (Math.floor(ExVectorY / 10) == 0) { ExVectorY = 1; }
        NewElement.ApplyForce(ExVectorX / 10, ExVectorY / 10, 1);

        //Hide old element and add new element as position fixed
        this.css('visibility', 'hidden');
        this.addClass('Xh');
        BodyRef.append(NewElement);

    }
});

Object.prototype.rotate = function (d) {
    var s = "rotate(" + d + "deg)";
    if (this.style) { // regular DOM Object
        this.style.MozTransform = s
        this.style.WebkitTransform = s;
        this.style.OTransform = s;
        this.style.transform = s;
        this.style.webkitTransform = s;
        this.style.webkitTransformOrigin = s;
    } else if (this.css) { // JQuery Object
        this.css("-moz-transform", s);
        this.css("-webkit-transform", s);
        this.css("-0-transform", s);
        this.css("transform", s);
        this.css("webkitTransform", s);
        this.css("WebkitTransformOrigin", s);
        this.attr("rotation", d);
    }
}

function convertTextNode(textNode) {

    //Looky here!
    //http://james.padolsey.com/javascript/replacing-text-in-the-dom-its-not-that-simple/

    var textStr = textNode.data.replace(/\s+/, '').replace('\n', '');
    var text = textStr.split(' ');

    for (var i = 0, len = text.length; i < len; i++) {
        text[i] = '<span class="Xi">' + text[i] + '</span>';
    }

    var temp = document.createElement('div');
    temp.innerHTML = text.join(' ');

    while (temp.firstChild) {
        DG(temp.firstChild.nodeType);
        textNode.parentNode.insertBefore(
            temp.firstChild,
            textNode);
    }
    textNode.parentNode.removeChild(textNode);

}


/********************* MISC ***********************/
function ParseXML(xmlStr) {
    if (window.DOMParser) {
        parser = new DOMParser();
        xmlDoc = parser.parseFromString(xmlStr, "text/xml");
        return xmlDoc.documentElement;
    }
    else // Internet Explorer
    {
        xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async = false;
        xmlDoc.loadXML(xmlStr);
        return xmlDoc.documentElement;
    } 
}

function RandomFromTo(from, to) {
    return Math.floor(Math.random() * (to - from + 1) + from);
}

function addcss(css) {
    var head = document.getElementsByTagName('head')[0];
    var styleElement = document.createElement('style');
    styleElement.setAttribute('type', 'text/css');
    if (styleElement.styleSheet) {   // IE
        styleElement.styleSheet.cssText = css;
    } else {                // the world
        styleElement.appendChild(document.createTextNode(css));
    }
    head.appendChild(styleElement);
}

function DG(msg) {
    jQuery('#debug').html(msg + '<br/>' + jQuery('#debug').html());
}
/********************* MISC END ********************/

var BodyRef = null;
$(document).ready(function () {
    BodyRef = $('body:first');
    $(document).click(function (e) {
        BlowUp(e.clientX, e.clientY);
    });
    ConvertPage_BlowUpable();
    Timer.Start();
});